#pragma once
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<cerrno>
#include<cstring>
#include<string>
#include "log.hpp"

class Sock
{
private:
    const static int gbacklog = 20;

public:
    Sock()
    {
    }

    int Socket()//创建套接字
    {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if(sock<0)
        {
            logMessage(FATAL,"create socket fail %d %s",errno,strerror(errno));
            exit(1);
        }
        logMessage(NORMAL,"create socket success,%d",sock);
        return sock;
    }
    void Bind( int sock, uint16_t port, std::string ip="0.0.0.0")//绑定
    {
        //把服务器的ip和port等信息填充到local结构体中
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(port);
        local.sin_addr.s_addr=inet_addr(ip.c_str());
        if(bind(sock,(sockaddr*)&local,sizeof(local))<0)
        {
            logMessage(FATAL,"bind fail,%d %s",errno,strerror(errno));
            exit(2);
        }
        logMessage(NORMAL,"bind success");
        

    }
    void Listen(int sock)//建立连接
    {
        if(listen(sock,gbacklog)<0)
        {
            logMessage(FATAL,"listen fail,%d %s",errno,strerror(errno));
            exit(3);
        }
        logMessage(NORMAL,"listen success");
    }
    //一般情况：
    //const std::string& 输入型参数
    //std::string* 输出型参数
    //std::string& 输入输出型参数
    int Accept(int sock,uint16_t*port,std::string* ip)//获取新连接
    {
        struct sockaddr_in src;
        memset(&src,0,sizeof(src));
        socklen_t len=sizeof(src);
        //获取新连接成功后，客户端的port和ip信息会填充到src结构体中
        int servicesock=accept(sock,(sockaddr*)&src,&len);
        
        if(servicesock<0)
        {
              logMessage(FATAL,"accept fail %d %s",errno,strerror(errno));
              return -1;
        }
        logMessage(NORMAL,"accept success");
        //获得客户端的port和ip信息
        if(port)
        {
            *port=ntohs(src.sin_port);
        }
        if(ip)
        {
            *ip=inet_ntoa(src.sin_addr);
        }
        return servicesock;
    }
    bool Connect(const int servicesock, uint16_t service_port, std::string& service_ip)//客户端进行连接服务器
    {
        struct sockaddr_in service;
        memset(&service,0,sizeof(service));
        service.sin_family=AF_INET;
        service.sin_port=htons(service_port);
        service.sin_addr.s_addr=inet_addr(service_ip.c_str());
        if(connect(servicesock,(sockaddr*)&service,sizeof(service))<0)
        {
            logMessage(FATAL,"connect error, %d %s",errno,strerror(errno));
           return false;
        }
        logMessage(NORMAL,"connect success");
        return true;


    }
    ~Sock()
    {
    }
};
